import math
import os
import platform
from pathlib import Path


class PathUtils:
    """路径管理工具类"""

    @staticmethod
    def get_absolute_path(relative_path):
        """将相对路径转换为绝对路径

        Args:
            relative_path: 相对路径

        Returns:
            str: 绝对路径
        """
        return os.path.abspath(relative_path)

    @staticmethod
    def get_relative_path(absolute_path, base_path):
        """将绝对路径转换为相对于基准路径的相对路径

        Args:
            absolute_path: 绝对路径
            base_path: 基准路径

        Returns:
            str: 相对路径
        """
        return os.path.relpath(absolute_path, base_path)

    @staticmethod
    def join_paths(*paths):
        """连接多个路径部分

        Args:
            *paths: 路径部分

        Returns:
            str: 连接后的路径
        """
        return os.path.join(*paths)

    @staticmethod
    def get_parent_directory(path):
        """获取父目录

        Args:
            path: 路径

        Returns:
            str: 父目录路径
        """
        return os.path.dirname(path)

    @staticmethod
    def get_file_name(path):
        """获取文件名（包括扩展名）

        Args:
            path: 路径

        Returns:
            str: 文件名
        """
        return os.path.basename(path)

    @staticmethod
    def get_file_name_without_extension(path):
        """获取不带扩展名的文件名

        Args:
            path: 路径

        Returns:
            str: 不带扩展名的文件名
        """
        file_name = os.path.basename(path)
        return os.path.splitext(file_name)[0]

    @staticmethod
    def get_file_extension(path):
        """获取文件扩展名

        Args:
            path: 路径

        Returns:
            str: 文件扩展名（包括点号）
        """
        return os.path.splitext(path)[1]

    @staticmethod
    def ensure_directory_exists(directory_path):
        """确保目录存在，如果不存在则创建

        Args:
            directory_path: 目录路径

        Returns:
            bool: 是否成功
        """
        try:
            os.makedirs(directory_path, exist_ok=True)
            return True
        except Exception as e:
            print(f"创建目录失败: {str(e)}")
            return False

    @staticmethod
    def is_directory(path):
        """检查路径是否为目录

        Args:
            path: 路径

        Returns:
            bool: 是否为目录
        """
        return os.path.isdir(path)

    @staticmethod
    def is_file(path):
        """检查路径是否为文件

        Args:
            path: 路径

        Returns:
            bool: 是否为文件
        """
        return os.path.isfile(path)

    @staticmethod
    def exists(path):
        """检查路径是否存在

        Args:
            path: 路径

        Returns:
            bool: 是否存在
        """
        return os.path.exists(path)

    @staticmethod
    def list_files(directory_path, pattern=None, recursive=False):
        """列出目录中的文件

        Args:
            directory_path: 目录路径
            pattern: 文件名匹配模式（如 "*.txt"）
            recursive: 是否递归列出子目录中的文件

        Returns:
            list: 文件路径列表
        """
        if not os.path.exists(directory_path) or not os.path.isdir(
            directory_path
        ):
            return []

        file_list = []

        if recursive:
            for root, dirs, files in os.walk(directory_path):
                for file in files:
                    file_path = os.path.join(root, file)
                    if pattern is None or Path(file).match(pattern):
                        file_list.append(file_path)
        else:
            for file in os.listdir(directory_path):
                file_path = os.path.join(directory_path, file)
                if os.path.isfile(file_path) and (
                    pattern is None or Path(file).match(pattern)
                ):
                    file_list.append(file_path)

        return file_list

    @staticmethod
    def list_directories(directory_path, recursive=False):
        """列出目录中的子目录

        Args:
            directory_path: 目录路径
            recursive: 是否递归列出子目录中的子目录

        Returns:
            list: 子目录路径列表
        """
        if not os.path.exists(directory_path) or not os.path.isdir(
            directory_path
        ):
            return []

        dir_list = []

        if recursive:
            for root, dirs, files in os.walk(directory_path):
                for dir in dirs:
                    dir_path = os.path.join(root, dir)
                    dir_list.append(dir_path)
        else:
            for item in os.listdir(directory_path):
                item_path = os.path.join(directory_path, item)
                if os.path.isdir(item_path):
                    dir_list.append(item_path)

        return dir_list

    @staticmethod
    def get_size(path):
        """获取文件或目录的大小

        Args:
            path: 路径

        Returns:
            int: 大小（字节）
        """
        if not os.path.exists(path):
            return 0

        if os.path.isfile(path):
            return os.path.getsize(path)
        else:
            total_size = 0
            for root, dirs, files in os.walk(path):
                for file in files:
                    file_path = os.path.join(root, file)
                    total_size += os.path.getsize(file_path)
            return total_size

    @staticmethod
    def get_human_readable_size(size_bytes):
        """将字节大小转换为人类可读的格式

        Args:
            size_bytes: 字节大小

        Returns:
            str: 人类可读的大小
        """
        if size_bytes == 0:
            return "0 Bytes"

        size_name = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
        i = int(math.floor(math.log(size_bytes, 1024)))
        p = math.pow(1024, i)
        s = round(size_bytes / p, 2)

        return f"{s} {size_name[i]}"

    @staticmethod
    def get_modified_time(path):
        """获取文件或目录的修改时间

        Args:
            path: 路径

        Returns:
            float: 修改时间（时间戳）
        """
        if not os.path.exists(path):
            return 0

        return os.path.getmtime(path)

    @staticmethod
    def get_creation_time(path):
        """获取文件或目录的创建时间

        Args:
            path: 路径

        Returns:
            float: 创建时间（时间戳）
        """
        if not os.path.exists(path):
            return 0

        if platform.system() == "Windows":
            return os.path.getctime(path)
        else:
            # 在Unix/Linux系统上，os.path.getctime返回的是inode修改时间
            # 使用stat模块获取更准确的信息
            stat_info = os.stat(path)
            try:
                # macOS
                return stat_info.st_birthtime
            except AttributeError:
                # Linux，回退到修改时间
                return stat_info.st_mtime

    @staticmethod
    def get_current_working_directory():
        """获取当前工作目录

        Returns:
            str: 当前工作目录路径
        """
        return os.getcwd()

    @staticmethod
    def get_script_directory():
        """获取当前脚本的目录

        Returns:
            str: 当前脚本的目录路径
        """
        return os.path.dirname(os.path.abspath(__file__))

    @staticmethod
    def get_project_root_directory():
        """获取项目根目录

        Returns:
            str: 项目根目录路径
        """
        # 假设此文件位于src/utils目录下，项目根目录是src的父目录
        current_dir = os.path.dirname(os.path.abspath(__file__))
        project_root = os.path.dirname(
            os.path.dirname(os.path.dirname(current_dir))
        )
        return project_root

    @staticmethod
    def normalize_path(path):
        """标准化路径（处理路径分隔符和相对路径）

        Args:
            path: 路径

        Returns:
            str: 标准化后的路径
        """
        return os.path.normpath(path)

    @staticmethod
    def get_temp_directory():
        """获取临时目录

        Returns:
            str: 临时目录路径
        """
        import tempfile

        return tempfile.gettempdir()

    @staticmethod
    def create_temp_file(suffix="", prefix="tmp", dir=None):
        """创建临时文件

        Args:
            suffix: 文件后缀
            prefix: 文件前缀
            dir: 临时文件目录

        Returns:
            tuple: (文件描述符, 文件路径)
        """
        import tempfile

        return tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)

    @staticmethod
    def create_temp_directory(suffix="", prefix="tmp", dir=None):
        """创建临时目录

        Args:
            suffix: 目录后缀
            prefix: 目录前缀
            dir: 临时目录的父目录

        Returns:
            str: 临时目录路径
        """
        import tempfile

        return tempfile.mkdtemp(suffix=suffix, prefix=prefix, dir=dir)

    @staticmethod
    def find_file(file_name, search_dir, recursive=True):
        """在指定目录中查找文件

        Args:
            file_name: 要查找的文件名
            search_dir: 搜索目录
            recursive: 是否递归搜索

        Returns:
            list: 找到的文件路径列表
        """
        if not os.path.exists(search_dir) or not os.path.isdir(search_dir):
            return []

        found_files = []

        if recursive:
            for root, dirs, files in os.walk(search_dir):
                if file_name in files:
                    found_files.append(os.path.join(root, file_name))
        else:
            for item in os.listdir(search_dir):
                item_path = os.path.join(search_dir, item)
                if os.path.isfile(item_path) and item == file_name:
                    found_files.append(item_path)

        return found_files

    @staticmethod
    def find_files_by_pattern(pattern, search_dir, recursive=True):
        """在指定目录中按模式查找文件

        Args:
            pattern: 文件匹配模式
            search_dir: 搜索目录
            recursive: 是否递归搜索

        Returns:
            list: 找到的文件路径列表
        """
        if not os.path.exists(search_dir) or not os.path.isdir(search_dir):
            return []

        found_files = []

        if recursive:
            for root, dirs, files in os.walk(search_dir):
                for file in files:
                    if Path(file).match(pattern):
                        found_files.append(os.path.join(root, file))
        else:
            for item in os.listdir(search_dir):
                item_path = os.path.join(search_dir, item)
                if os.path.isfile(item_path) and Path(item).match(pattern):
                    found_files.append(item_path)

        return found_files

    @staticmethod
    def add_to_path(path):
        """将路径添加到系统PATH环境变量

        Args:
            path: 要添加的路径
        """
        if path not in os.environ["PATH"]:
            os.environ["PATH"] = path + os.pathsep + os.environ["PATH"]

    @staticmethod
    def get_path_env_var():
        """获取系统PATH环境变量

        Returns:
            list: PATH中的路径列表
        """
        return os.environ["PATH"].split(os.pathsep)
